home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-07-09 | 15.9 KB | 561 lines | [TEXT/CWIE] |
- // MSGXPrinting.c
- //
- // Original version by Jon Lansdell and Nigel Humphreys.
- // 4.0 and 3.1 updates by Greg Sutton.
- // GX printing by Don Swatman
- // ©Apple Computer Inc 1996, all rights reserved.
-
- // Adds GX printing functionality to MenuScripter
-
- /*
- Changes for 4.0
-
- 29-Feb-96 : GS : Changed <Graphics routines.h> to <GXGraphics.h>
- Changed <graphics toolbox.h> to <GXEnvironment.h>
- */
-
- #include <Gestalt.h>
-
- #ifdef __MWERKS__
- #include <Graphics routines.h>
- #include <graphics toolbox.h>
- #else
- #include <GXGraphics.h>
- #include <GXPrinting.h>
- #endif
-
- #include <GXEnvironment.h>
- #include "QDLibrary.h"
-
-
- #include "MSGXPrinting.h"
- #include "MSWindow.h"
- #include "MSGlobals.h"
- #include "MSMain.h"
- #include "MSAEWindowUtils.h"
-
- // Constants
-
- #define kGraphicsHeapSize ((long) 300 * 1024)
-
- // Globals
- gxGraphicsClient gClient;
-
-
- //-------------------------------------------------------
- // InitGXIfPresent
- //
- // This uses Gestalt() to see if QuickDraw GX is present.
- // If it is, it then initialises the GX managers.
- // If it isn't, then it removes the GX file menu item(s).
- //-------------------------------------------------------
-
- #pragma segment Main
-
- void InitGXIfPresent(void)
- {
- long gxVersion;
- long gxPrintVersion;
-
- gGXIsPresent = false;
-
- // Check to see whether QuickDraw GX is available.
- if (Gestalt(gestaltGXVersion, &gxVersion) == noErr)
- if (Gestalt(gestaltGXPrintingMgrVersion, &gxPrintVersion) == noErr)
- gGXIsPresent = true;
-
- if (gGXIsPresent)
- {
- // Initialize QuickDraw GX.
- gClient = GXNewGraphicsClient(nil, kGraphicsHeapSize, (gxClientAttribute) 0);
- GXEnterGraphics();
- GXInitPrinting();
- }
- else
- {
- // No QuickDraw GX, so remove extra file menu item(s)
- DelMenuItem ( myMenus[fileM], fmPrintOne);
- }
- }
-
- //-------------------------------------------------------
- // CleanUpGXIfPresent
- //
- // If GX was installed (i.e. gGXIsPresent) then remove
- // the GX managers.
- //-------------------------------------------------------
-
- #pragma segment Main
-
- void CleanUpGXIfPresent(void)
- {
- if (gGXIsPresent)
- {
- GXExitPrinting();
- GXDisposeGraphicsClient(gClient);
- GXExitGraphics();
- }
- }
-
- //-------------------------------------------------------
- // ConvertMenuActualToGXMenu
- //
- // This converts an item number as returned by MenuKey()
- // or MenuSelect() to the value used internally. The reason
- // you have to this is because a non gx application has
- // less items in the file menu.
- //-------------------------------------------------------
-
- #pragma segment Main
-
- short ConvertMenuActualToGXMenu ( short theItem )
- {
- short menuItem;
-
- menuItem = theItem;
- if (!gGXIsPresent)
- {
- if (theItem == fmNoGXPrint)
- menuItem = fmPrint;
- else
- if (theItem == fmNoGXQuit)
- menuItem = fmQuit;
- }
- return menuItem;
- }
-
- //-------------------------------------------------------
- // GetRectOfPage
- //
- // This returns a QuickDraw rect for the current printer page.
- // If gx is not present if uses rPage from the document's THPrint.
- // If gx is present then we get a GXRectangle from the requested
- // page's format. It then converts this to a Rect. This could be
- // extended to handle custom formated pages.
- //-------------------------------------------------------
-
- #pragma segment Main
-
- void GetRectOfPage( DPtr theDoc,
- Rect *pageRect )
- {
- gxFormat pageFormat;
- gxRectangle pageSize;
- gxRectangle paperSize;
-
- if (gGXIsPresent)
- {
- pageFormat = GXGetJobFormat(theDoc->documentJob, 1);
- GXGetFormatDimensions(pageFormat, &pageSize, &paperSize);
- // Convert to a QD Rect
- FixedRectToShort( &pageSize, pageRect );
- }
- else
- *pageRect = (*(theDoc->thePrintSetup))->prInfo.rPage;
- OffsetRect( pageRect, -pageRect->left, -pageRect->top);
- }
-
- //-------------------------------------------------------
- // AdjustMenusForGXPrintDialogs
- //
- // This enables or disables menu's when the GX print dialog
- // is being displayed.
- //-------------------------------------------------------
-
- #pragma segment GXPrintSeg
-
- void AdjustMenusForGXPrintDialogs( Boolean dialogGoingUp )
- {
- Boolean redrawMenuBar = false;
-
- if (dialogGoingUp)
- {
- SetMenuItemState ( false, myMenus[appleM], aboutItem);
- redrawMenuBar |= SetMenuItemState ( false, myMenus[fileM], kMenuTitle );
- if ( CountDocuments( ) )
- {
- redrawMenuBar |= SetMenuItemState ( false, myMenus[fontM], kMenuTitle);
- redrawMenuBar |= SetMenuItemState ( false, myMenus[sizeM], kMenuTitle);
- redrawMenuBar |= SetMenuItemState ( false, myMenus[styleM], kMenuTitle);
-
- redrawMenuBar |= SetMenuItemState ( false, myMenus[scriptM], kMenuTitle);
- redrawMenuBar |= SetMenuItemState ( false, myMenus[subroutineM], kMenuTitle);
-
- SetMenuItemState ( false, myMenus[editM], selectAllCommand);
- }
- HiliteMenu(0);
-
- }
- else
- {
- SetMenuItemState ( true, myMenus[appleM], aboutItem);
- redrawMenuBar |= SetMenuItemState ( true, myMenus[fileM], kMenuTitle);
- redrawMenuBar |= SetMenuItemState ( true, myMenus[editM], kMenuTitle);
- if ( CountDocuments( ) )
- {
- redrawMenuBar |= SetMenuItemState ( true, myMenus[fontM], kMenuTitle);
- redrawMenuBar |= SetMenuItemState ( true, myMenus[sizeM], kMenuTitle);
- redrawMenuBar |= SetMenuItemState ( true, myMenus[styleM], kMenuTitle);
-
- redrawMenuBar |= SetMenuItemState ( true, myMenus[scriptM], kMenuTitle);
- redrawMenuBar |= SetMenuItemState ( true, myMenus[subroutineM], kMenuTitle);
-
- SetMenuItemState ( true, myMenus[editM], selectAllCommand);
- }
- MaintainMenus( &redrawMenuBar );
- }
-
- if (redrawMenuBar)
- DrawMenuBar();
- }
-
- //-------------------------------------------------------
- // SetupGXEditMenuRec
- //
- // Sets up the gxEditMenuRecord. This is used by the
- // GX dialogs so that they know where the items in the
- // Edit Menu are
- //-------------------------------------------------------
-
- #pragma segment GXPrintSeg
-
- void SetupGXEditMenuRec(gxEditMenuRecord *editMenuRec)
- {
- editMenuRec->editMenuID = editID;
- editMenuRec->cutItem = cutCommand;
- editMenuRec->copyItem = copyCommand;
- editMenuRec->pasteItem = pasteCommand;
- editMenuRec->clearItem = clearCommand;
- editMenuRec->undoItem = undoCommand;
- }
-
- //-------------------------------------------------------
- // DoGXPageSetup
- //
- // Puts up a GX Page Setup dialog
- //-------------------------------------------------------
-
- #pragma segment GXPrintSeg
-
- Boolean DoGXPageSetup ( DPtr theDoc )
- {
- Boolean result = false;
- OSErr theErr;
- gxDialogResult dialogResult;
- gxEditMenuRecord editMenuRec;
-
- if (gGXIsPresent)
- if (theDoc)
- {
- AdjustMenusForGXPrintDialogs(true);
- SetupGXEditMenuRec( &editMenuRec );
-
- // Display the Page Setup dialog box.
- dialogResult = GXJobDefaultFormatDialog ( theDoc->documentJob, &editMenuRec);
- theErr = GXGetJobError(theDoc->documentJob);
-
- AdjustMenusForGXPrintDialogs(false);
-
- // Return True, if there are no Errors and the OK button was clicked
- result = ((theErr == noErr) && (dialogResult == gxOKSelected));
- }
- return(result);
- }
-
-
- //-------------------------------------------------------
- // struct GXPrintSpoolDataRec
- //
- // Used to pass information during printing
- //-------------------------------------------------------
-
- typedef struct GXPrintSpoolDataRec
- {
- gxRectangle pageArea; // Page rectangle.
- gxViewPort printViewPort; // View port we're printing in.
- } GXPrintSpoolDataRec, *GXPrintSpoolDataPtr;
-
- //-------------------------------------------------------
- // PrintAShape
- //
- // Called after shape translation. It checks to see if any shape
- // it recieves are drawable, the draws it in the GX view port.
- // Information in the form of a pointer to a GXPrintSpoolDataRec
- // is passed in the refCon.
- //-------------------------------------------------------
-
- #pragma segment GXPrintSeg
-
- OSErr PrintAShape(gxShape currentShape, long refCon)
- {
- GXPrintSpoolDataPtr spoolData;
- gxShapeType theShapeType;
-
- // Get the spool data from the refCon
- spoolData = (GXPrintSpoolDataPtr) refCon;
-
- // Don't waste time spooling the shape if it's being drawn off the page.
-
- theShapeType = GXGetShapeType(currentShape);
- if ( (theShapeType == gxEmptyType)
- || (theShapeType == gxFullType)
- || (theShapeType == gxPictureType)
- || GXTouchesBoundsShape(&spoolData->pageArea, currentShape) )
- {
-
- // Set the ports and draw it
- GXSetShapeViewPorts(currentShape, 1, &spoolData->printViewPort);
- GXDrawShape(currentShape);
- }
- return (OSErr) GXGetGraphicsError(nil);
- }
-
- //-------------------------------------------------------
- // DuplicateStyleTERec
- //
- // This copies the styled TERec in theDoc. It puts it into
- // the destPort
- //-------------------------------------------------------
-
- #pragma segment Main
-
- void DuplicateStyleTERec( TEHandle hSourceTE,
- TEHandle *hDestTE,
- Rect *destRect,
- GrafPtr destPort )
- {
- GrafPtr oldPort;
- short oldSelStart;
- short oldSelEnd;
- StScrpHandle printerTextStyles;
-
- // Set up the ports
- GetPort(&oldPort);
- SetPort(destPort);
-
- // Create a temporary Text Edit and copy the windows text edit into it
- *hDestTE = TEStyleNew(destRect, destRect);
-
- // Select all the text (preserving the previous settings) so that we can use
- // GetTylScrap (or TEGetStyleScrapHandle ) to get the style of the whole TERec
- oldSelStart = (*hSourceTE)->selStart;
- oldSelEnd = (*hSourceTE)->selEnd;
- TESetSelect(0,(*hSourceTE)->teLength, hSourceTE);
-
- // Get the style
- printerTextStyles = GetStylScrap(hSourceTE);
-
- // Revert the selection range
- TESetSelect(oldSelStart, oldSelEnd, hSourceTE);
-
- // Move the text from the documents TERec and add the style (got above) to it
- HLock((Handle)((*hSourceTE)->hText));
- TEStyleInsert ( (Ptr)*((*hSourceTE)->hText),
- (*hSourceTE)->teLength,
- printerTextStyles,
- *hDestTE);
- HUnlock((Handle)((*hSourceTE)->hText));
-
- // Deactivat the temporary TERec
- TEDeactivate(*hDestTE);
-
- // Reset the port
- SetPort(oldPort);
- }
-
- //-------------------------------------------------------
- // GXPrintLoop
- //
- // This does the actual printing. It creates a invisible window
- // to draw into. It duplicates the Text Edit record in the
- // document to a temporary record. It puts up the progress
- // dialog then it steps through the pages. At each page, it
- // clips the text edit rec so it doesn't draw lines of text
- // over two pages. It then uses TEUpdate to draw each page and
- // finally scroll's the text edit rec ready for the next page.
- //-------------------------------------------------------
-
-
- #pragma segment GXPrintSeg
-
- OSErr GXPrintLoop ( DPtr theDoc)
- {
- OSErr theErr = noErr;
- WindowPtr imagingWind; // Temp window we're going to draw into
- gxViewPort printViewPort; // Printer view port
- Rect tempWindRect = {0,0,0,0}; // Bounds for temp window
- TEHandle tempTE; // Copy of the documents text edit record
- PageEndsArray pageEnds;
- short numDocPages;
- long firstPage;
- long lastPage;
- long numPagesToPrint;
- long pageCounter;
- Point patStretch = {1,1};
- gxFormat pageFormat;
- Rect everywhereRect;
- Str255 windTitle;
- GXPrintSpoolDataRec spoolData;
- Rect printerPage;
- Rect rectToClip;
-
- // Create a window to draw into. It's bounds are small(0,0,0,0)
- // and it's not shown so it doesn't appear to the user
- imagingWind = NewWindow ( nil, &tempWindRect, "\p",
- false, documentProc, (WindowPtr)-1,
- false, 0);
-
- // Set the port to the imaging port
- SetPort((GrafPtr)imagingWind);
-
- // Get the size of the printers page
- GetRectOfPage ( theDoc, &printerPage );
-
- // Duplicate the text edit record from the document
- DuplicateStyleTERec( theDoc->theText, &tempTE, &printerPage, (GrafPtr)imagingWind );
-
-
- // Work out the size of each page using GetPageEnds. This stops text
- // drawing over two pages
-
- (*tempTE)->destRect = printerPage;
- GetPageEnds(printerPage.bottom-printerPage.top,
- tempTE,
- pageEnds,
- &numDocPages);
-
-
- // Determine which pages the user selected to print, and print
- // only those pages that are actually in the document.
- GXGetJobPageRange(theDoc->documentJob, &firstPage, &lastPage);
- if (lastPage > numDocPages)
- lastPage = numDocPages;
-
- // Calculate the number of pages to print and begin printing.
- numPagesToPrint = lastPage - firstPage + 1;
- theErr = GXGetJobError(theDoc->documentJob);
- if (!theErr)
- {
- // Get the title of the window as we'll use this for the name we call the print job
- GetWTitle ( theDoc->theWindow, windTitle);
-
- // Put up the print progress dialog
- GXStartJob( theDoc->documentJob,
- windTitle,
- numPagesToPrint);
- theErr = GXGetJobError(theDoc->documentJob);
- if (!theErr)
- {
- // Create a new view port for printing and set our translator
- // rects to "wide open" so that they include all data we're
- // drawing. For each page we print, call GXStartPage, draw,
- // and call GXFinishPage.
- SetRect(&everywhereRect, 0, 0, 32767, 32767);
- printViewPort = GXNewViewPort(gxScreenViewDevices);
-
- for (pageCounter = firstPage; (theErr == noErr) && (pageCounter <= lastPage); pageCounter++)
- {
- // Get the page's format and start printing the page.
- pageFormat = GXGetJobFormat(theDoc->documentJob, 1);
-
- GXStartPage(theDoc->documentJob, pageCounter, pageFormat, 1, &printViewPort);
- theErr = GXGetJobError(theDoc->documentJob);
-
- // If there were no errors, set up the translator, draw
- // the QuickDraw data for current page, and remove the
- // translator.
- if (!theErr)
- {
- // Set up spool data
- spoolData.printViewPort = printViewPort;
- GXGetFormatDimensions( pageFormat, &spoolData.pageArea, nil);
-
- // Install the translator
- GXInstallQDTranslator((GrafPtr)imagingWind,
- gxDefaultOptionsTranslation,
- &everywhereRect,
- &everywhereRect,
- patStretch,
- NewgxShapeSpoolProc ( PrintAShape ),
- &spoolData);
-
- // Make sure it draws into the correct QuickDraw window
- SetPort((GrafPtr)imagingWind);
-
- // Clip the page to the size of the current page
- rectToClip = printerPage;
- if (pageCounter == 1)
- rectToClip.bottom = rectToClip.top + pageEnds[pageCounter-1];
- else
- rectToClip.bottom = rectToClip.top
- + ( pageEnds[pageCounter-1] - pageEnds[pageCounter-2] );
- ClipRect(&rectToClip);
-
- // Use TEUpdate to do the drawing
- TEUpdate(&printerPage, tempTE);
-
- // Remove the Translator
- GXRemoveQDTranslator((GrafPtr)imagingWind, nil);
-
- // Finish off this page
- GXFinishPage(theDoc->documentJob);
-
- // Scroll the text edit down to the next page
- if (pageCounter < lastPage)
- TEScroll(0,rectToClip.top-rectToClip.bottom, tempTE);
- }
- }
- // All done, so finish the printer job and dispose of the GXView port
- GXFinishJob(theDoc->documentJob);
- theErr = GXGetJobError(theDoc->documentJob);
- GXDisposeViewPort(printViewPort);
- }
- }
-
- // Dispose of temporary TERec and imaging window
- TEDispose ( tempTE );
- DisposeWindow ( imagingWind );
-
- return theErr;
- }
-
- //-------------------------------------------------------
- // GXPrintDocument
- //
- // This puts up the print dialog box, then calls GXPrintLoop()
- // to do the actual printing.
- //-------------------------------------------------------
-
- #pragma segment GXPrintSeg
-
- OSErr GXPrintDocument ( DPtr theDoc,
- Boolean askUser )
- {
- OSErr err = noErr;
- gxEditMenuRecord editMenuRec;
- gxDialogResult dialogResult;
-
- // Put up the print dialog if askUser is set to true
- if (!askUser)
- dialogResult = gxOKSelected;
- else
- {
- // Set up the edit menu record so GX knows how to gray it
- SetupGXEditMenuRec( &editMenuRec );
-
- AdjustMenusForGXPrintDialogs(true);
- dialogResult = GXJobPrintDialog(theDoc->documentJob,
- &editMenuRec);
- AdjustMenusForGXPrintDialogs(false);
- }
-
- // if ok selected, then print the pages
- if (dialogResult == gxOKSelected)
- err = GXPrintLoop(theDoc);
- else
- err = userCanceledErr;
-
- return err;
- }
-
-